using System;
using fit;
using fitnesse.handlers;

namespace SCSoft.WinForms.Tests
{
    public class DateTimeSubstitutionHandler : AbstractCellHandler
    {
        public const string TODAY = "TODAY";

        public static void InjectDateTimeSubstitutions()
        {
            var handler = new DateTimeSubstitutionHandler();
            Configuration.Instance.AddHandler(handler);
        }

        public override bool Match(string searchString, Type type)
        {
            if (searchString.StartsWith(TODAY))
            {
                return true;
            }

            bool matches = type.Equals(typeof (DateTime));
            return matches;
        }

        public override void HandleInput(Fixture fixture, Parse cell, Accessor accessor)
        {
            DateTime theDateTime = GetDateTime(cell.Text);
            accessor.Set(fixture, theDateTime);
        }

        public override bool HandleEvaluate(Fixture fixture, Parse cell, Accessor accessor)
        {
            DateTime expected = GetDateTime(cell.Text);
            var actual = (DateTime) accessor.Get(fixture);
            return expected.Date.Equals(actual.Date);
        }

        public static DateTime GetDateTime(string dateString)
        {
            string trimmedString = dateString.Trim();
            if (trimmedString == TODAY)
            {
                return DateTime.Today;
            }

            if (trimmedString.Contains(TODAY))
            {
                string dayString = trimmedString.Substring(5, trimmedString.Length - 5);
                int days = int.Parse(dayString);

                return DateTime.Today.AddDays(days);
            }

            return DateTime.Parse(trimmedString);
        }

        public bool CanParse(Type theType, Parse theValueCell)
        {
            return theType.Equals(typeof (DateTime));
        }

        public object Parse(Type theType, Parse theValueCell, object theTarget)
        {
            return GetDateTime(theValueCell.Text);
        }
    }

    public class NullableDateTimeSubstitutionHandler : AbstractCellHandler
    {
        public const string NULL = "NULL";
        public const string TODAY = "TODAY";

        public static void InjectDateTimeSubstitutions()
        {
            Configuration.Instance.AddHandler(new NullableDateTimeSubstitutionHandler());
        }

        public override bool Match(string searchString, Type type)
        {
            return type.Equals(typeof (DateTime?));
        }

        public override void HandleInput(Fixture fixture, Parse cell, Accessor accessor)
        {
            DateTime? theDateTime = GetDateTime(cell.Text);
            accessor.Set(fixture, theDateTime);
        }

        public override bool HandleEvaluate(Fixture fixture, Parse cell, Accessor accessor)
        {
            DateTime? expected = GetDateTime(cell.Text);
            DateTime? actual = (DateTime) accessor.Get(fixture);
            return (!expected.HasValue && !actual.HasValue) ||
                   (expected.HasValue && actual.HasValue &&
                    expected.Value.Date.Equals(actual.Value.Date));
        }

        public static DateTime? GetDateTime(string dateString)
        {
            string trimmedString = dateString.Trim();
            if (trimmedString == TODAY)
            {
                return DateTime.Today;
            }
            if (trimmedString == NULL)
            {
                return null;
            }

            if (trimmedString.Contains(TODAY))
            {
                string dayString = trimmedString.Substring(5, trimmedString.Length - 5);
                int days = int.Parse(dayString);

                return DateTime.Today.AddDays(days);
            }

            return DateTime.Parse(trimmedString);
        }
    }
}